<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>取消请求</button>
    <script>
        // console.dir(axios);
        // 1. request
        // 2. put post get ...
        // 3. interceptors
        // 4. defaults
        function InterceptorManager() {
            this.handler = []
        }
        InterceptorManager.prototype.use = function (onResolve, onReject) {
            this.handler.push({
                success: onResolve,
                fail: onReject
            });
        }

        function Axios(config) {
            this.defaults = config;
            this.interceptors = {
                request: new InterceptorManager(),
                response: new InterceptorManager()
            }
        }

        Axios.prototype.request = function(config) {
            console.log('request this: ', this);

            const dispatch = () => {
                // 发送请求
                return new Promise((resolve, reject) => {
                    const xhr = new XMLHttpRequest();
                    console.log('config',config);
                    xhr.open(config.method, config.url);
                    xhr.send()
                    xhr.onreadystatechange = function(){
                        if(xhr.readyState === 4) {
                            if(/^2\d{2}$/.test(xhr.status)){
                                console.log(23);
                                resolve(xhr.response);
                            }else{
                                reject(xhr.status);
                            }
                        }
                    }
                    if(config.cancelToken){
                        console.log('cancelToken');
                        config.cancelToken.promise.then(()=>{
                            xhr.abort();
                        })
                    }
                })
            }
            const chain = [dispatch, undefined];
            this.interceptors.request.handler.forEach(item => {
                chain.unshift(item.success, item.fail)
            })
            this.interceptors.response.handler.forEach(item => {
                chain.push(item.success, item.fail)
            })

            let promise = Promise.resolve();
            while(chain.length){
                promise = promise.then(chain.shift(), chain.shift())
            }
            promise.then(data=>{
                console.log('chain data: ', data);
            })
            return promise;
        }

        function createInstance(config) {
            const context = new Axios(config);
            let instance = Axios.prototype.request.bind(context);
            Object.keys(context).forEach(item => {
                instance[item] = context[item];
            })
            return instance;
        }

        function CancelToken(executor){
            let outPromise = null;
            this.promise = new Promise((resolve, reject)=>{
                outPromise = resolve
            })
            executor(()=>{
                outPromise();
            })
        }



        const axios = createInstance({ method: 'get' });

        axios.CancelToken = CancelToken;

        axios.interceptors.request.use(config1 => {
            return config1;
        }, error1 => {

        })
        axios.interceptors.request.use(config2 => {
            return config2;
        }, error2 => {

        })

        axios.interceptors.response.use(response1 => {
            return response1
        }, error1 => {

        })
        axios.interceptors.response.use(response2 => {
            return response2
        }, error2 => {

        })

        let cancel = null;
        axios({ 
            method: 'get' ,
            url:'http://localhost:8080/timeout',
            cancelToken: new axios.CancelToken((c)=>{
                cancel = c;
            })
        }).then(data=>{
            console.log('data: ', data);
        })

        
        let oBtn = document.querySelector('button');
        oBtn.onclick = function(){
            cancel();
        }

    </script>
</body>

</html>